package service

import (
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"seat-service/initialization"
	"seat-service/model"
	"seat-service/model/dto"
	"seat-service/utils"
	"strconv"
)

type SeatService struct {
}

func (*SeatService) DeleteByBuildingIDsWithTransaction(tx *gorm.DB, ids []int) error {
	err := tx.Where("building_id in ?", ids).Delete(&model.Seat{}).Error
	if err != nil {
		// 删除redis缓存
		idsStr := make([]string, 0, len(ids))
		for _, s := range ids {
			idsStr = append(idsStr, strconv.Itoa(s))
		}
		utils.DeleteMapKey(utils.BuildingData, idsStr)
		utils.DeleteMapKey(utils.BuildingId, idsStr)
	}
	return err
}

func (s *SeatService) GetByClassroomID(classroomID uint) (seats []model.Seat, err error) {
	err = initialization.DB.Where("classroom_id = ?", classroomID).Find(&seats).Error
	return
}

func (*SeatService) GetByIdWithTransaction(tx *gorm.DB, seatID uint) (seat model.Seat, err error) {
	err = tx.Clauses(clause.Locking{Strength: "UPDATE"}).Where("id = ?", seatID).Find(&seat).Error
	return
}

func (*SeatService) AddSeat(seat model.Seat) error {
	err := initialization.DB.Create(&seat).Error
	if err != nil {
		return err
	}
	return nil
}
func (*SeatService) BatchAddSeat(seatDto []dto.BatchAddSeatDto) (int, error) {
	index := 0
	for _, v := range seatDto {
		var campus model.Campus
		var building model.Building
		var classroom model.Classroom
		err := initialization.DB.Model(&model.Campus{}).Where("campus_name=?", v.Campus).First(&campus).Error
		if err != nil {
			return index, err
		}
		err = initialization.DB.Model(&model.Building{}).Where("name=? AND campus_id=?", v.Building, campus.ID).First(&building).Error
		if err != nil {
			return index, err
		}
		err = initialization.DB.Model(&model.Classroom{}).Where("location=? AND campus_id=? AND building_id=?", v.Classroom, campus.ID, building.ID).First(&classroom).Error
		if err != nil {
			return index, err
		}
		seat := model.Seat{
			CampusId:    campus.ID,
			BuildingId:  building.ID,
			ClassroomID: classroom.ID,
			SeatNumber:  v.SeatNumber,
			SeatStatus:  v.SeatStatus,
		}
		err = initialization.DB.Create(&seat).Error
		if err != nil {
			return index, err
		}
		index++
	}

	return index, nil
}
func (*SeatService) DelSeat(id uint) error {
	err := initialization.DB.Delete(&model.Seat{}, id).Error
	if err != nil {
		return err
	}
	return nil
}
func (*SeatService) BatchDelSeat(delDto dto.BatchDelDto) error {
	err := initialization.DB.Transaction(func(tx *gorm.DB) error {
		for _, v := range delDto.Id {
			err := tx.Delete(&model.Seat{}, v).Error
			if err != nil {
				return err
			}
		}
		return nil
	})
	if err != nil {
		return err
	}
	return nil
}

func (*SeatService) UpdateSeat(seat model.Seat) error {
	err := initialization.DB.Updates(&seat).Update("seat_status", seat.SeatStatus).Error
	if err != nil {
		return err
	}
	return nil
}
func (*SeatService) QuerySeat(page, pageSize int) (dto.QuerySeatReturnDto2, error) {

	results := make([]dto.QuerySeatReturn, 0)

	var record int64
	err := initialization.DB.
		Table("seats s1").
		Joins("JOIN campus c1 ON s1.campus_id = c1.id").
		Joins("JOIN buildings b1 ON s1.building_id = b1.id").
		Joins("JOIN classrooms c2 ON s1.classroom_id = c2.id").
		Select("s1.id, s1.campus_id, s1.building_id, s1.classroom_id,s1.seat_number, s1.seat_reserve, s1.seat_status,c1.campus_name,b1.name,c2.location").
		Where("s1.deleted_at IS NULL AND c1.deleted_at IS NULL AND b1.deleted_at IS NULL AND c2.deleted_at IS NULL").
		Count(&record).Error
	if err != nil {
		return dto.QuerySeatReturnDto2{}, err
	}
	//页数
	pages := (record + int64(pageSize) - 1) / int64(pageSize)

	// 构建查询语句
	err = initialization.DB.
		Table("seats s1").
		Joins("JOIN campus c1 ON s1.campus_id = c1.id").
		Joins("JOIN buildings b1 ON s1.building_id = b1.id").
		Joins("JOIN classrooms c2 ON s1.classroom_id = c2.id").
		Select("s1.id, s1.campus_id, s1.building_id, s1.classroom_id,s1.seat_number, s1.seat_reserve, s1.seat_status,c1.campus_name,b1.name,c2.location").
		Where("s1.deleted_at IS NULL AND c1.deleted_at IS NULL AND b1.deleted_at IS NULL AND c2.deleted_at IS NULL").
		Order("s1.id ASC").
		Offset((page - 1) * pageSize).Limit(pageSize).
		Find(&results).Error
	if err != nil {
		return dto.QuerySeatReturnDto2{}, err
	}
	return dto.QuerySeatReturnDto2{
		Record: record,
		Pages:  pages,
		Seat:   results,
	}, nil
}

func (*SeatService) QuerySeatTabulationCampus() ([]model.Campus, error) {

	campus := make([]model.Campus, 0)

	err := initialization.DB.Model(&model.Campus{}).Find(&campus).Error
	if err != nil {
		return nil, err
	}
	return campus, nil
}
func (*SeatService) QuerySeatTabulationBuilding(campusId uint) ([]model.Building, error) {
	building := make([]model.Building, 0)
	err := initialization.DB.Model(&model.Building{}).Where("campus_id=?", campusId).Find(&building).Error
	if err != nil {
		return nil, err
	}
	return building, nil
}
func (*SeatService) QuerySeatTabulationClassroom(buildingId uint) ([]model.Classroom, error) {
	classroom := make([]model.Classroom, 0)
	err := initialization.DB.Model(&model.Classroom{}).Where("building_id=?", buildingId).Find(&classroom).Error
	if err != nil {
		return nil, err
	}
	return classroom, nil
}

func (*SeatService) QueryConditionSeat(seatDto dto.ConditionSeatDto) (dto.QuerySeatReturnDto2, error) {
	page := seatDto.Page
	pageSize := seatDto.PageSize
	results := make([]dto.QuerySeatReturn, 0)

	var record int64
	err := initialization.DB.
		Table("seats s1").
		Joins("JOIN campus c1 ON s1.campus_id = c1.id").
		Joins("JOIN buildings b1 ON s1.building_id = b1.id").
		Joins("JOIN classrooms c2 ON s1.classroom_id = c2.id").
		Select("s1.id, s1.campus_id, s1.building_id, s1.classroom_id,s1.seat_number, s1.seat_reserve, s1.seat_status,c1.campus_name,b1.name,c2.location").
		Where("s1.campus_id LIKE ? AND s1.building_id LIKE ? AND s1.classroom_id LIKE ? AND s1.seat_number Like ?  AND s1.seat_status LIKE ? AND c2.location LIKE ? AND b1.name LIKE ? AND s1.deleted_at IS NULL AND c1.deleted_at IS NULL AND b1.deleted_at IS NULL AND c2.deleted_at IS NULL ",
			seatDto.CampusId, seatDto.BuildingId, seatDto.ClassroomId, "%"+seatDto.SeatNumber+"%", seatDto.SeatStatus, "%"+seatDto.ClassroomName+"%", "%"+seatDto.BuildingName+"%").
		Count(&record).Error
	if err != nil {
		return dto.QuerySeatReturnDto2{}, err
	}
	//页数
	pages := (record + int64(pageSize) - 1) / int64(pageSize)

	// 构建查询语句
	err = initialization.DB.
		Table("seats s1").
		Joins("JOIN campus c1 ON s1.campus_id = c1.id").
		Joins("JOIN buildings b1 ON s1.building_id = b1.id").
		Joins("JOIN classrooms c2 ON s1.classroom_id = c2.id").
		Select("s1.id, s1.campus_id, s1.building_id, s1.classroom_id,s1.seat_number, s1.seat_reserve, s1.seat_status,c1.campus_name,b1.name,c2.location").
		Order("s1.id ASC").
		Where("s1.campus_id LIKE ? AND s1.building_id LIKE ? AND s1.classroom_id LIKE ? AND s1.seat_number Like ? AND s1.seat_status LIKE ? AND c2.location LIKE ? AND b1.name LIKE ? AND s1.deleted_at IS NULL AND c1.deleted_at IS NULL AND b1.deleted_at IS NULL AND c2.deleted_at IS NULL ",
			seatDto.CampusId, seatDto.BuildingId, seatDto.ClassroomId, "%"+seatDto.SeatNumber+"%", seatDto.SeatStatus, "%"+seatDto.ClassroomName+"%", "%"+seatDto.BuildingName+"%").
		Order("s1.id ASC").
		Offset((page - 1) * pageSize).Limit(pageSize).
		Find(&results).Error
	if err != nil {
		return dto.QuerySeatReturnDto2{}, err
	}
	return dto.QuerySeatReturnDto2{
		Record: record,
		Pages:  pages,
		Seat:   results,
	}, nil

}
func (*SeatService) QueryById(id uint) ([]dto.QuerySeatReturn, error) {
	res := make([]dto.QuerySeatReturn, 0)
	err := initialization.DB.
		Table("seats s1").
		Joins("JOIN campus c1 ON s1.campus_id = c1.id").
		Joins("JOIN buildings b1 ON s1.building_id = b1.id").
		Joins("JOIN classrooms c2 ON s1.classroom_id = c2.id").
		Select("s1.id, s1.campus_id, s1.building_id, s1.classroom_id,s1.seat_number, s1.seat_reserve, s1.seat_status,c1.campus_name,b1.name,c2.location").
		Where("s1.deleted_at IS NULL AND c1.deleted_at IS NULL AND b1.deleted_at IS NULL AND c2.deleted_at IS NULL AND s1.id=?", id).
		Scan(&res).Error
	if err != nil {
		return nil, err
	}
	return res, nil
}
